package com.task.core.service.impl;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.annotation.Resource;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.task.common.constant.ErrorCodeConstants;
import com.task.common.enums.*;
import com.task.common.redis.RedisKeyConstants;
import com.task.core.domain.*;
import com.task.core.domain.info.*;
import com.task.core.dto.request.DatasourceOptionRequestDTO;
import com.task.core.dto.response.MissionHistoryDetailResposeDTO;
import com.task.core.dto.response.SysFileInfoResponseDTO;
import com.task.core.mapper.DataOperationMapper;
import com.task.core.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageInfo;
import com.task.common.annotation.DataScope;
import com.task.common.core.redis.RedisCache;
import com.task.common.domain.info.KeyAndValue;
import com.task.common.domain.info.PlanInfo;
import com.task.common.exception.ServiceException;
import com.task.common.info.DeviceFraudInfo;
import com.task.common.info.DeviceGroupInfo;
import com.task.common.info.FlowFilterInfo;
import com.task.common.info.IpFraudInfo;
import com.task.common.info.PluginInfo;
import com.task.common.info.ProxyInfo;
import com.task.common.info.QuestionShowInfo;
import com.task.common.info.RelationMissionDeviceFraud;
import com.task.common.info.RelationMissionDeviceGroup;
import com.task.common.info.RelationMissionFlowFilter;
import com.task.common.info.RelationMissionIpFraud;
import com.task.common.info.RelationMissionPlugin;
import com.task.common.info.RelationMissionProxy;
import com.task.common.utils.SecurityUtils;
import com.task.common.utils.StringUtils;
import com.task.common.utils.SystemFunctionUtil;
import com.task.common.utils.constants.RedisConstants;
import com.task.common.utils.date.DateUtil;
import com.task.core.dto.request.CountryRequestDTO;
import com.task.core.dto.request.MissionRequestDTO;
import com.task.core.dto.request.info.HistoryDataSearchInfo;
import com.task.core.dto.response.MissionPageResultResponseDTO;
import com.task.core.mapper.MissionMapper;
import com.task.core.mapper.SysFileMapper;

/**
 * @author 迪迦.
 * @date 2024/11/4 17:28
 */
@Service("MissionService")
public class MissionServiceImpl implements MissionService {

  @Resource
  private RedisCache redisService;

  @Resource
  private MissionMapper missionMapper;
  @Resource
  private RefererSourceService refererSourceService;

  @Resource
  private DatasourceService datasourceService;

  @Resource
  private SysFileMapper sysFileMapper;

  @Resource
  private DataSendByMissionService dataSendByMissionService;

  @Resource
  private CountryService countryService;

  @Resource
  private PlanService planService;

  @Resource
  private DeviceService deviceService;

  @Resource
  private DeviceGroupService deviceGroupService;

  @Resource
  private SendHistoryService sendHistoryService;

  @Resource
  private QuestionInfoService questionInfoService;

  @Resource
  private EngineSchemeService engineSchemeService;

  @Resource
  private DataOperationMapper dataOperationMapper;

  @Resource
  private DataPreAvailableService dataPreAvailableService;

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public MissionPageResultResponseDTO  getMissionByPage(MissionRequestDTO request) {
    //request.setOperationBy(SecurityUtils.checkAdmin());
    List<MissionInfo> missionByPage = missionMapper.getMissionByPage(request);
    List<MissionPageInfo> pageInfos = new ArrayList<>();
    //国家
    List<KeyAndValue> countryInfos = countryService.getCountryForOption(new CountryRequestDTO());
    //计划
    List<PlanInfo> planInfos = planService.getAllPlan();
    WeekEnum week = DateUtil.getWeek();
    //获取当前小时
    int currentHour = DateUtil.getCurrentHour();
    List<HistoryDataSearchInfo> searchTableList = sendHistoryService.getSearchTableList(SystemFunctionUtil.HISTORY_MISSION_GET_DETAIL,
        request.getStartTime(), request.getEndTime());
    for (MissionInfo missionInfo : missionByPage) {
      MissionPageInfo missionPageInfo = new MissionPageInfo();
      missionPageInfo.setMissionInfo(missionInfo);

      //添加国家
      KeyAndValue country = countryInfos.stream().filter(f -> f.getValue().equals(missionInfo.getCountryCode())).findFirst().orElse(null);
      missionPageInfo.setCountryName(country == null ? null : country.getKey());

      //添加计划
      PlanInfo planInfo = planInfos.stream().filter(f -> f.getCode().equals(missionInfo.getPlanCode())).findFirst().orElse(null);
      if (!ObjectUtils.isEmpty(planInfo)) {
        MissionPlanInfo missionPlanInfo = new MissionPlanInfo();
        missionPlanInfo.setPlanName(planInfo.getPlanName());
        //获取当前小时数量,然后乘以cap值,向上取整
        String planDayJson = SystemFunctionUtil.getPlanDayJson(planInfo, week);
        if (!StringUtils.isEmpty(planDayJson)) {
          List<PlanJsonConfig> planJsonConfig = JSONArray.parseArray(planDayJson, PlanJsonConfig.class);
          PlanJsonConfig planJsonByHour = planJsonConfig.stream().filter(f -> f.getHour() == currentHour)
              .findFirst().orElse(null);
          if (!ObjectUtils.isEmpty(planJsonByHour)) {
            //具体值用百分比算出来
            BigDecimal divideNum = new BigDecimal(ObjectUtils.isEmpty(planJsonByHour.getCount()) ? 0 : planJsonByHour.getCount()).divide(
                new BigDecimal(100), 2, RoundingMode.HALF_UP);
            //当前小时最多能获取多少次
            BigDecimal cap = new BigDecimal(missionInfo.getLimitationCount());
            BigDecimal hourCount = cap.multiply(divideNum)
                .setScale(0, RoundingMode.HALF_UP);
            hourCount = hourCount.compareTo(cap) > 0 ? cap : hourCount;
            missionPlanInfo.setCountNowHour(hourCount);
            missionPageInfo.setPlanInfo(missionPlanInfo);
          }
        }
      }

      //添加设备
      //获取任务关联的所有分组下面的设备
      MissionDeviceGroupInfo missionDeviceInfo = new MissionDeviceGroupInfo();
      List<DeviceGroupInfo> deviceGroupInfos = deviceGroupService.getDeviceGroupByMissionCode(missionInfo.getCode());
      if (!CollectionUtils.isEmpty(deviceGroupInfos)) {
        List<DeviceInfo> deviceInfos = deviceService.getDeviceListByGroupCodes(deviceGroupInfos.stream().map(DeviceGroupInfo::getCode).collect(
            Collectors.toList()));
        if (!CollectionUtils.isEmpty(deviceInfos)) {
          List<ClientDeviceAndGroupInfo> clientDeviceAndGroupInfos = new ArrayList<>();
          missionDeviceInfo.setDeviceCount(deviceInfos.size());
          for (DeviceGroupInfo deviceGroupInfo : deviceGroupInfos) {
            List<DeviceInfo> deviceByGroup = deviceInfos.stream().filter(f -> f.getDeviceGroupCode().equals(deviceGroupInfo.getCode()))
                .collect(Collectors.toList());
            clientDeviceAndGroupInfos.add(new ClientDeviceAndGroupInfo(deviceGroupInfo.getDeviceGroupName(), deviceByGroup));
          }
          missionDeviceInfo.setDeviceAndGroupInfos(clientDeviceAndGroupInfos);
        }
      }
      missionPageInfo.setDeviceGroupInfo(missionDeviceInfo);

      //获取时间段当前任务被请求的记录
      List<MissionHistoryDetailResposeDTO> missionSendHistoryInfos = null;
      if (!CollectionUtils.isEmpty(searchTableList)) {
        missionSendHistoryInfos = sendHistoryService.getMissionSendHistoryByTimeType(searchTableList, missionInfo.getCode());
      }
      missionPageInfo.setMissionOfSendHistoryInfo(new MissionOfSendHistoryInfo(missionSendHistoryInfos));

      //添加每个数据源和数据源使用状态
      //dataSource
      List<RelationMissionSourceUseDataCountInfo> dataSourceInfos = new ArrayList<>();
      if (!StringUtils.isEmpty(missionInfo.getDataSourceConfig())) {
        SourceConfig datasourceConfig = JSONObject.parseObject(missionInfo.getDataSourceConfig(), SourceConfig.class);
        if (!CollectionUtils.isEmpty(datasourceConfig.getSourceCodeList())) {
          List<RelationMissionSourceUseDataCountInfo> infos = missionMapper.getRelationMissionSourceUseDataCountInfoByMissionCode(
              missionInfo.getCode());
          if (!CollectionUtils.isEmpty(infos)) {
            dataSourceInfos.addAll(infos);
          }
        }
      }
      //refererSource
      //List<RelationMissionSourceUseDataCountInfo> refererSourceInfos = new ArrayList<>();
      //if (!StringUtils.isEmpty(missionInfo.getRefererSourceConfig())) {
      //  SourceConfig sourceConfig = JSONObject.parseObject(missionInfo.getRefererSourceConfig(), SourceConfig.class);
      //  if (!CollectionUtils.isEmpty(sourceConfig.getSourceCodeList())) {
      //    List<RelationMissionSourceUseDataCountInfo> infos = refererSourceService.getMissionPageRefererInfoByRefererCodes(
      //        sourceConfig.getSourceCodeList());
      //    if (!CollectionUtils.isEmpty(infos)) {
      //      refererSourceInfos.addAll(infos);
      //    }
      //  }
      //}
      missionPageInfo.setSourceInfo(new MissionDataTypeSourceInfo(dataSourceInfos, null));

      //查询有问题的关联字段,三个平台,代理,引擎方案
      //relation_mission_device_fraud
      List<QuestionShowInfo> showInfos = new ArrayList<>();
      deviceFraudsQuestion(missionInfo, missionPageInfo,showInfos);

      //relation_mission_ip_fraud
      ipFraudsQuestion(missionInfo, missionPageInfo,showInfos);

      //relation_mission_plugin
      pluginQuestion(missionInfo, missionPageInfo,showInfos);

      //relation_mission_proxy
      proxyQuestion(missionInfo, missionPageInfo,showInfos);

      //data_engine_scheme
      engineSchemeQuestion(missionInfo, missionPageInfo,showInfos);

      //添加无可用数据源问题
      missionQuestion(missionInfo.getCode(),missionPageInfo,showInfos);

      pageInfos.add(missionPageInfo);
    }
    return new MissionPageResultResponseDTO(pageInfos, new PageInfo(missionByPage).getTotal());
  }

  private void engineSchemeQuestion(MissionInfo missionInfo, MissionPageInfo missionPageInfo, List<QuestionShowInfo> showInfos) {
    List<QuestionShowInfo> engineSchemeQuestion = questionInfoService.getQuestionInfosByTypeAndCode(QuestionInfoTypeEnum.ENGINE.name(), missionInfo.getBrowserEnginesConfigCode());
    engineSchemeQuestion.stream().
            forEach(f ->{
              EngineSchemeInfo engineSchemeByCode = engineSchemeService.getEngineSchemeByCode(f.getDataCode());
              if( QuestionOperationTypeEnum.DELETE.getCode().equals(f.getOperationType()) &&
                      QuestionInfoTypeEnum.ENGINE.name().equals(f.getQuestionType()) ){

                if(!ObjectUtils.isEmpty(engineSchemeByCode)){
                  f.setShowContent(engineSchemeByCode.getEngineSchemeName() +","+ QuestionPromptContentEnum.ENGINE_DELETE_PROMPT_CONTENT.getMsg());
                }

              }else {
                if(!ObjectUtils.isEmpty(engineSchemeByCode)){
                  f.setShowContent(engineSchemeByCode.getEngineSchemeName()+","+ f.getShowContent());
                }

              }
            });
    if (!CollectionUtils.isEmpty(engineSchemeQuestion)) {
      showInfos.addAll(engineSchemeQuestion);
      missionPageInfo.setQuestionInfos(showInfos);
    }
  }

  private void proxyQuestion(MissionInfo missionInfo, MissionPageInfo missionPageInfo, List<QuestionShowInfo> showInfos) {
    List<ProxyInfo> proxiesByCode = getProxiesByCode(missionInfo.getCode());
    if (!CollectionUtils.isEmpty(proxiesByCode)) {
      List<QuestionShowInfo> question = questionInfoService.getQuestionInfosByTypeAndCodes(QuestionInfoTypeEnum.PROXY.name(),
          proxiesByCode.stream().map(ProxyInfo::getCode).collect(Collectors.toList()));
          question.stream().
                  forEach(f ->{
                    if( QuestionOperationTypeEnum.DELETE.getCode().equals(f.getOperationType()) &&
                            QuestionInfoTypeEnum.PROXY.name().equals(f.getQuestionType()) ){
                      f.setShowContent(
                              proxiesByCode.stream().filter(proxyInfo -> proxyInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getProxyName() +","+
                              QuestionPromptContentEnum.PROXY_DELETE_PROMPT_CONTENT.getMsg());
                    }else {
                      f.setShowContent(
                              proxiesByCode.stream().filter(proxyInfo -> proxyInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getProxyName() +","+
                                      f.getShowContent()
                      );
                    }
                  });
      if (!CollectionUtils.isEmpty(question)) {
        showInfos.addAll(question);
        missionPageInfo.setQuestionInfos(showInfos);
      }
    }
  }

  private void pluginQuestion(MissionInfo missionInfo, MissionPageInfo missionPageInfo, List<QuestionShowInfo> showInfos) {
    List<PluginInfo> pluginsByCode = getPluginsByCode(missionInfo.getCode());
    if (!CollectionUtils.isEmpty(pluginsByCode)) {
      List<QuestionShowInfo> questions = questionInfoService.getQuestionInfosByTypeAndCodes(QuestionInfoTypeEnum.PLUGIN.name(),
          pluginsByCode.stream().map(PluginInfo::getCode).collect(Collectors.toList()));
          questions.stream().
              forEach(f ->{
                if( QuestionOperationTypeEnum.DELETE.getCode().equals(f.getOperationType()) &&
                        QuestionInfoTypeEnum.PLUGIN.name().equals(f.getQuestionType()) ){
                  f.setShowContent(
                          pluginsByCode.stream().filter(pluginInfo -> pluginInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getPluginName() +","+
                          QuestionPromptContentEnum.PLUGIN_DELETE_PROMPT_CONTENT.getMsg());
                }else {
                  f.setShowContent(
                          pluginsByCode.stream().filter(pluginInfo -> pluginInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getPluginName() +","+
                                  f.getShowContent()
                  );
                }
              });
      if (!CollectionUtils.isEmpty(questions)) {
        showInfos.addAll(questions);
        missionPageInfo.setQuestionInfos(showInfos);
      }
    }
  }

  private void ipFraudsQuestion(MissionInfo missionInfo, MissionPageInfo missionPageInfo, List<QuestionShowInfo> questionShowInfos) {
    List<IpFraudInfo> ipFraudsByCode = getIpFraudsByCode(missionInfo.getCode());
    if (!CollectionUtils.isEmpty(ipFraudsByCode)) {
      List<QuestionShowInfo> questions = questionInfoService.getQuestionInfosByTypeAndCodes(QuestionInfoTypeEnum.IP_FRAUD.name(),
          ipFraudsByCode.stream().map(IpFraudInfo::getCode).collect(Collectors.toList()));
          questions.stream().
                forEach(f ->{
                  if( QuestionOperationTypeEnum.DELETE.getCode().equals(f.getOperationType()) &&
                          QuestionInfoTypeEnum.IP_FRAUD.name().equals(f.getQuestionType()) ){
                    f.setShowContent(
                            ipFraudsByCode.stream().filter(ipFraudInfo -> ipFraudInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getIpFraudName() +","+
                            QuestionPromptContentEnum.IP_FRAUD_DELETE_PROMPT_CONTENT.getMsg());
                  }else {
                    f.setShowContent(
                            ipFraudsByCode.stream().filter(ipFraudInfo -> ipFraudInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getIpFraudName() +","+
                                    f.getShowContent()
                    );
                  }
                });
      if (!CollectionUtils.isEmpty(questions)) {
        questionShowInfos.addAll(questions);
        missionPageInfo.setQuestionInfos(questionShowInfos);
      }
    }
  }

  private void deviceFraudsQuestion(MissionInfo missionInfo, MissionPageInfo missionPageInfo, List<QuestionShowInfo> questionShowInfos) {
    List<DeviceFraudInfo> deviceFraudsByCode = getDeviceFraudsByCode(missionInfo.getCode());
    if (!CollectionUtils.isEmpty(deviceFraudsByCode)) {
      List<QuestionShowInfo> questions = questionInfoService.getQuestionInfosByTypeAndCodes(QuestionInfoTypeEnum.DEVICE_FRAUD.name(),
          deviceFraudsByCode.stream().map(DeviceFraudInfo::getCode).collect(Collectors.toList()));
           questions.stream().
              forEach(f ->{
                if( QuestionOperationTypeEnum.DELETE.getCode().equals(f.getOperationType()) &&
                        QuestionInfoTypeEnum.DEVICE_FRAUD.name().equals(f.getQuestionType())
                       ){
                  f.setShowContent(
                          deviceFraudsByCode.stream().filter(deviceFraudInfo -> deviceFraudInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getDeviceFraudName() +","+
                          QuestionPromptContentEnum.DEVICE_FRAUD_DELETE_PROMPT_CONTENT.getMsg());
                }else {
                  f.setShowContent(
                          deviceFraudsByCode.stream().filter(deviceFraudInfo -> deviceFraudInfo.getCode().equals(f.getDataCode())).findFirst().orElse(null).getDeviceFraudName() +","+
                                  f.getShowContent()
                  );
                }
              });
      if (!CollectionUtils.isEmpty(questions)) {
        questionShowInfos.addAll(questions);
        missionPageInfo.setQuestionInfos(questionShowInfos);
      }
    }
  }

  private void missionQuestion(String missionCode, MissionPageInfo missionPageInfo, List<QuestionShowInfo> showInfos) {
    QuestionShowInfo missionQuestion = questionInfoService.getQuestionInfosByMissionTypeAndCode(QuestionInfoTypeEnum.MISSION.name(), missionCode);
    if(!ObjectUtils.isEmpty(missionQuestion)){
      missionQuestion.setShowContent(ErrorCodeConstants.AVAILABLE_DATA_SOURCE_IS_USED.getMsg());
      showInfos.add(missionQuestion);
      missionPageInfo.setQuestionInfos(showInfos);
    }
  }

  @Override
  public MissionInfo getMissionByCode(String code, boolean detail)  {
    MissionInfo missionByCode = redisService.getCacheObject(RedisKeyConstants.MISSION_INFO.formatKey(code));
    if(ObjectUtils.isEmpty(missionByCode)){
       missionByCode = missionMapper.getMissionByCode(code);

      if (ObjectUtils.isEmpty(missionByCode)) {
        throw new ServiceException(ErrorCodeConstants.MISSION_NOT_EXIST.getMsg());
      }

      redisService.setCacheObject(RedisKeyConstants.MISSION_INFO.formatKey(missionByCode.getCode()), missionByCode);
    }

    getMissionDetail(code, detail, missionByCode);

    return missionByCode;
  }

  private void getMissionDetail(String code, boolean detail, MissionInfo missionByCode) {
    try {
      if (detail) {
        missionByCode.setDeviceFrauds(getDeviceFraudsByCode(code));
        missionByCode.setDeviceGroups(getDeviceGroupsByCode(code));
        missionByCode.setFlowFilterRules(getFlowFiltersByCode(code));
        missionByCode.setIpFrauds(getIpFraudsByCode(code));
        missionByCode.setProxies(getProxiesByCode(code));
        missionByCode.setPlugins(getPluginsByCode(code));
//        if (!StringUtils.isEmpty(missionByCode.getScriptFileCode())) {
//          missionByCode.setFileInfo(sysFileMapper.getFileByCode(missionByCode.getScriptFileCode()));
//        }
        if(!StringUtils.isEmpty(missionByCode.getScriptFileCodeJson())){

          ObjectMapper objectMapper = new ObjectMapper();
          List<String> codes = objectMapper.readValue(missionByCode.getScriptFileCodeJson(), new TypeReference<List<String>>() {});
          missionByCode.setScriptFileCodes(codes);
          List<SysFileInfoResponseDTO> sysFileInfos=sysFileMapper.getFilesByCodes(codes);
          missionByCode.setFileInfos(sysFileInfos);

        }
      }
    }catch (IOException e) {
      e.printStackTrace();
    }
  }

  private List<PluginInfo> getPluginsByCode(String code) {
    List<PluginInfo> pluginInfos = new ArrayList<>();
    List<RelationMissionPlugin> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_PLUGIN.formatKey(code));
    List<String> emptyList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionPlugin relationMissionPlugin : list) {
        PluginInfo data = redisService.getCacheObject(RedisKeyConstants.PLUGIN_INFO.formatKey(relationMissionPlugin.getPluginCode()));
        if (!ObjectUtils.isEmpty(data)) {
          pluginInfos.add(data);
        } else {
          emptyList.add(relationMissionPlugin.getPluginCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(pluginInfos)) {
      pluginInfos.addAll(missionMapper.getPluginsByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyList)) {
      pluginInfos.addAll(missionMapper.getPluginsByCodes(emptyList));
    }
    return pluginInfos;
  }

  private List<ProxyInfo> getProxiesByCode(String code) {
    List<ProxyInfo> proxyInfos = new ArrayList<>();
    List<RelationMissionProxy> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_PROXY.formatKey(code));
    List<String> emptyList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionProxy info : list) {
        ProxyInfo data = redisService.getCacheObject(RedisKeyConstants.PROXY_INFO.formatKey(info.getProxyCode()));
        if (!ObjectUtils.isEmpty(data)) {
          proxyInfos.add(data);
        } else {
          emptyList.add(info.getProxyCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(proxyInfos)) {
      proxyInfos.addAll(missionMapper.getProxiesByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyList)) {
      proxyInfos.addAll(missionMapper.getProxiesByCodes(emptyList));
    }
    return proxyInfos;
  }

  private List<IpFraudInfo> getIpFraudsByCode(String code) {
    List<IpFraudInfo> ipFraudInfos = new ArrayList<>();
    List<RelationMissionIpFraud> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_IP_FRAUD.formatKey(code));
    List<String> emptyList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionIpFraud info : list) {
        IpFraudInfo data = redisService.getCacheObject(RedisKeyConstants.IP_FRAUD_INFO.formatKey(info.getIpFraudCode()));
        if (!ObjectUtils.isEmpty(data)) {
          ipFraudInfos.add(data);
        } else {
          emptyList.add(info.getIpFraudCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(ipFraudInfos)) {
      ipFraudInfos.addAll(missionMapper.getIpFraudsByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyList)) {
      ipFraudInfos.addAll(missionMapper.getIpFraudsByCodes(emptyList));
    }
    return ipFraudInfos;

  }

  private List<FlowFilterInfo> getFlowFiltersByCode(String code) {
    List<FlowFilterInfo> flowFilterInfos = new ArrayList<>();
    List<RelationMissionFlowFilter> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_FLOW_FILTER.formatKey(code));
    List<String> emptyList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionFlowFilter info : list) {
        FlowFilterInfo data = redisService.getCacheObject(RedisKeyConstants.FLOW_FILTER_INFO.formatKey(info.getFlowFilterCode()));
        if (!ObjectUtils.isEmpty(data)) {
          flowFilterInfos.add(data);
        } else {
          emptyList.add(info.getFlowFilterCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(flowFilterInfos)) {
      flowFilterInfos.addAll(missionMapper.getFlowFiltersByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyList)) {
      flowFilterInfos.addAll(missionMapper.getFlowFiltersByCodes(emptyList));
    }
    return flowFilterInfos;

  }

  private List<DeviceGroupInfo> getDeviceGroupsByCode(String code) {
    List<DeviceGroupInfo> deviceGroupInfos = new ArrayList<>();
    List<RelationMissionDeviceGroup> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_DEVICE_GROUP.formatKey(code));
    List<String> emptyCode = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionDeviceGroup info : list) {
        DeviceGroupInfo data = redisService.getCacheObject(RedisKeyConstants.DEVICE_GROUP_INFO.formatKey(info.getDeviceGroupCode()));
        if (!ObjectUtils.isEmpty(data)) {
          deviceGroupInfos.add(data);
        } else {
          emptyCode.add(info.getDeviceGroupCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(deviceGroupInfos)) {
      deviceGroupInfos.addAll(missionMapper.getDeviceGroupsByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyCode)) {
      deviceGroupInfos.addAll(missionMapper.getDeviceGroupsByCodes(emptyCode));
    }
    return deviceGroupInfos;

  }

  private List<DeviceFraudInfo> getDeviceFraudsByCode(String code) {
    List<DeviceFraudInfo> deviceFraudInfos = new ArrayList<>();
    List<RelationMissionDeviceFraud> list = redisService.getCacheObject(RedisKeyConstants.RELATION_MISSION_DEVICE_FRAUD.formatKey(code));
    List<String> emptyList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(list)) {
      for (RelationMissionDeviceFraud info : list) {
        DeviceFraudInfo data = redisService.getCacheObject(RedisKeyConstants.DEVICE_FRAUD_INFO.formatKey(info.getDeviceFraudCode()));
        if (!ObjectUtils.isEmpty(data)) {
          deviceFraudInfos.add(data);
        } else {
          emptyList.add(info.getDeviceFraudCode());
        }
      }
    }
    if (CollectionUtils.isEmpty(deviceFraudInfos)) {
      deviceFraudInfos.addAll(missionMapper.getDeviceFraudsByCode(code));
    }else if (!CollectionUtils.isEmpty(emptyList)) {
      deviceFraudInfos.addAll(missionMapper.getDeviceFraudsByCodes(emptyList));
    }
    return deviceFraudInfos;

  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<KeyAndValue> getMissionForOption(MissionRequestDTO request) {
    //request.setOperationBy(SecurityUtils.checkAdmin());
    return missionMapper.getMissionForOption(request);
  }

  @Transactional
  @Override
  public void addMission(MissionRequestDTO request) {
    String code = UUID.randomUUID().toString().replace("-", "");
    request.setCode(code);
    request.setOperationBy(SecurityUtils.getLoginUser().getUserId());
    String scriptCodes = JSONArray.toJSONString(request.getScriptFileCodes());
    request.setScriptFileCodeToJson(scriptCodes);

    SourceConfig sourceConfig = JSONObject.parseObject(request.getDataSourceConfig(), SourceConfig.class);
    if(sourceConfig.getStatus()){
      throw new ServiceException(ErrorCodeConstants.EDIT_DATA_SOURCE_IS_ALLOW.getMsg());
    }

    //添加任务信息
    missionMapper.addMission(request);
    //解析数据源
    //更新或添加任务跟设备关联使用数据状态表
    addOrUpdateMissionUseDataHistory(request);
    //添加关联的分组信息
    if (!CollectionUtils.isEmpty(request.getDeviceGroupCodes())) {
      missionMapper.addMissionDeviceGroupRelation(request.getDeviceGroupCodes(), code);
      addMissionDeviceGroupRelationRedis(request.getDeviceGroupCodes(), code);
    }
    //添加关联的deviceFraud信息
    if (!CollectionUtils.isEmpty(request.getDeviceFraudCodes())) {
      missionMapper.addMissionDeviceFraudRelation(request.getDeviceFraudCodes(), code);
      addMissionDeviceFraudRelationRedis(request.getDeviceFraudCodes(), code);
    }
    //添加关联的FLOW_FILTER信息
    if (!CollectionUtils.isEmpty(request.getFlowFilterRuleCodes())) {
      missionMapper.addMissionFlowFilterRelation(request.getFlowFilterRuleCodes(), code);
      addMissionFlowFilterRelationRedis(request.getFlowFilterRuleCodes(), code);
    }
    //添加关联的IP_FRAUD信息
    if (!CollectionUtils.isEmpty(request.getIpFraudCodes())) {
      missionMapper.addMissionIpFraudRelation(request.getIpFraudCodes(), code);
      addMissionIpFraudRelationRedis(request.getIpFraudCodes(), code);
    }
    //添加关联的Plugin信息
    if (!CollectionUtils.isEmpty(request.getPluginCodes())) {
      missionMapper.addMissionPluginRelation(request.getPluginCodes(), code);
      addMissionPluginRelationRedis(request.getPluginCodes(), code);
    }
    //添加关联的proxy信息
    if (!CollectionUtils.isEmpty(request.getProxyCodes())) {
      missionMapper.addMissionProxyRelation(request.getProxyCodes(), code);
      addMissionProxyRelationRedis(request.getProxyCodes(), code);
    }
  }

  private void addOrUpdateMissionUseDataHistory(MissionRequestDTO request) {
    if (StringUtils.isEmpty(request.getDataSourceConfig())) {
      return;
    }
    SourceConfig sourceConfig = JSONObject.parseObject(request.getDataSourceConfig(),
        SourceConfig.class);
    if (ObjectUtils.isEmpty(sourceConfig) || CollectionUtils.isEmpty(sourceConfig.getSourceCodeList())) {
      return;
    }
    addSourceRelation(request, sourceConfig.getSourceCodeList());
    //查询需要关联的数据源数据
    List<DatasourceInfo> dataSources = datasourceService.getDataSourceByCodes(sourceConfig.getSourceCodeList());
    List<RelationMissionSourceUseDataCount> addList = new ArrayList<>();
    List<RelationMissionSourceUseDataCount> updateList = new ArrayList<>();
    //查询已经关联过的数据源数据
    List<RelationMissionSourceUseDataCount> useDataInfos = missionMapper.getInfoByMissionCode(request.getCode());
    if (CollectionUtils.isEmpty(useDataInfos)) {
      //全是新增
      dataSources.forEach(f -> {
        addList.add(
            new RelationMissionSourceUseDataCount(UUID.randomUUID().toString().replace("-", ""), request.getCode(),
                f.getCode(), DataFileTypeEnum.DATA.name(), f.getDataCount(), 0, true));
      });
    } else {
      //更新
      for (DatasourceInfo datasourceInfo : dataSources) {
        //通过已经有的查找新操作的
        RelationMissionSourceUseDataCount useData = useDataInfos.stream().filter(f -> f.getSourceCode().equals(datasourceInfo.getCode())).findFirst()
            .orElse(null);
        if (useData == null) {
          //新增
          addList.add(new RelationMissionSourceUseDataCount(UUID.randomUUID().toString().replace("-", ""), request.getCode(),
              datasourceInfo.getCode(), DataFileTypeEnum.DATA.name(), datasourceInfo.getDataCount(), 0, true));
        } else {
          //修改
          if (useData.getUseStatus()) {
            //正在使用
            //更新他的使用情况
            updateList.add(new RelationMissionSourceUseDataCount(useData.getCode(), null, null, null, datasourceInfo.getDataCount(), null, true));
          } else {
            //已经删除掉但现在又加回来
            updateList.add(new RelationMissionSourceUseDataCount(useData.getCode(), null, null, null, datasourceInfo.getDataCount(), null, true));
          }
        }
      }
      //查看需要删除的,
      List<String> requestDatasourceCodes = dataSources.stream().map(DatasourceInfo::getCode).collect(Collectors.toList());
      for (RelationMissionSourceUseDataCount useDataInfo : useDataInfos) {
        if (!requestDatasourceCodes.contains(useDataInfo.getSourceCode())) {
          //提交的数据没有,数据库有,说明是需要解除关联
          updateList.add(new RelationMissionSourceUseDataCount(useDataInfo.getCode(), null, null, null, null, null, false));
        }
      }
    }

    if (!CollectionUtils.isEmpty(addList)) {
      missionMapper.addMissionAndSourceUseCount(addList);
    }
    if (!CollectionUtils.isEmpty(updateList)) {
      for (RelationMissionSourceUseDataCount useDataInfo : updateList) {
        missionMapper.updateMissionAndSourceUseCount(useDataInfo);
      }
    }
  }

  private void addSourceRelation(MissionRequestDTO request, List<String> sourceCodeList) {
    //删除数据源关联表数据
    datasourceService.deleteDatasourceByMissionCode(request.getCode());
    //添加数据源关联表数据
    List<RelationMissionSourceInfo> sourceInfos = new ArrayList<>();
    sourceCodeList.forEach(f -> {
      sourceInfos.add(new RelationMissionSourceInfo(request.getCode(), f, DataFileTypeEnum.DATA.name()));
    });
    if (!StringUtils.isEmpty(request.getRefererSourceConfig())) {
      SourceConfig refererSourceConfig = JSONObject.parseObject(request.getRefererSourceConfig(),
          SourceConfig.class);
      if (!ObjectUtils.isEmpty(refererSourceConfig) && !CollectionUtils.isEmpty(refererSourceConfig.getSourceCodeList())) {
        refererSourceConfig.getSourceCodeList().forEach(f -> {
          sourceInfos.add(new RelationMissionSourceInfo(request.getCode(), f, DataFileTypeEnum.REFERER.name()));
        });
      }
    }
    if (!CollectionUtils.isEmpty(sourceInfos)) {
      datasourceService.addSourceByMissionCode(sourceInfos);
    }
  }

  private void addMissionProxyRelationRedis(List<String> proxyCodes, String code) {
    List<RelationMissionProxy> list = new ArrayList<>();
    proxyCodes.forEach(f -> {
      list.add(new RelationMissionProxy("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_PROXY.formatKey(code), list);
  }

  private void addMissionPluginRelationRedis(List<String> pluginCodes, String code) {
    List<RelationMissionPlugin> list = new ArrayList<>();
    pluginCodes.forEach(f -> {
      list.add(new RelationMissionPlugin("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_PLUGIN.formatKey(code), list);
  }

  private void addMissionIpFraudRelationRedis(List<String> ipFraudCodes, String code) {
    List<RelationMissionIpFraud> list = new ArrayList<>();
    ipFraudCodes.forEach(f -> {
      list.add(new RelationMissionIpFraud("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_IP_FRAUD.formatKey(code), list);
  }

  private void addMissionFlowFilterRelationRedis(List<String> flowFilterRuleCodes, String code) {
    List<RelationMissionFlowFilter> list = new ArrayList<>();
    flowFilterRuleCodes.forEach(f -> {
      list.add(new RelationMissionFlowFilter("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_FLOW_FILTER.formatKey(code), list);
  }

  private void addMissionDeviceFraudRelationRedis(List<String> deviceFraudCodes, String code) {
    List<RelationMissionDeviceFraud> list = new ArrayList<>();
    deviceFraudCodes.forEach(f -> {
      list.add(new RelationMissionDeviceFraud("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_DEVICE_FRAUD.formatKey(code), list);
  }

  private void addMissionDeviceGroupRelationRedis(List<String> deviceGroupCodes, String code) {
    List<RelationMissionDeviceGroup> list = new ArrayList<>();
    deviceGroupCodes.forEach(f -> {
      list.add(new RelationMissionDeviceGroup("", "", code, f));
    });
    redisService.setCacheObject(RedisKeyConstants.RELATION_MISSION_DEVICE_GROUP.formatKey(code), list);
  }

  @Transactional
  @Override
  public void modifyMission(MissionRequestDTO request) {
    request.setOperationBy(SecurityUtils.getLoginUser().getUserId());

    //多个脚本文件
    List<String> scriptFileCodes = request.getScriptFileCodes();
    String scriptFileCodesJson = JSONArray.toJSONString(scriptFileCodes);
    request.setScriptFileCodeToJson(scriptFileCodesJson);

    //过滤任务下关联的数据源的可用数量为零
    filterDataSoucureAvailable(request);

    Integer integer = missionMapper.modifyMission(request);
    if (integer == 0) {
      throw new ServiceException("code不存在");
    }
    deleteCache(request.getCode());
    //解析数据源
    //更新或添加任务跟设备关联使用数据状态表
    addOrUpdateMissionUseDataHistory(request);
    //添加关联的分组信息
    if (!CollectionUtils.isEmpty(request.getDeviceGroupCodes())) {
      missionMapper.addMissionDeviceGroupRelation(request.getDeviceGroupCodes(), request.getCode());
      addMissionDeviceGroupRelationRedis(request.getDeviceGroupCodes(), request.getCode());
    }
    //添加关联的deviceFraud信息
    if (!CollectionUtils.isEmpty(request.getDeviceFraudCodes())) {
      missionMapper.addMissionDeviceFraudRelation(request.getDeviceFraudCodes(), request.getCode());
      addMissionDeviceFraudRelationRedis(request.getDeviceFraudCodes(), request.getCode());
    }
    //添加关联的FLOW_FILTER信息
    if (!CollectionUtils.isEmpty(request.getFlowFilterRuleCodes())) {
      missionMapper.addMissionFlowFilterRelation(request.getFlowFilterRuleCodes(), request.getCode());
      addMissionFlowFilterRelationRedis(request.getFlowFilterRuleCodes(), request.getCode());
    }
    //添加关联的IP_FRAUD信息
    if (!CollectionUtils.isEmpty(request.getIpFraudCodes())) {
      missionMapper.addMissionIpFraudRelation(request.getIpFraudCodes(), request.getCode());
      addMissionIpFraudRelationRedis(request.getIpFraudCodes(), request.getCode());
    }
    //添加关联的Plugin信息
    if (!CollectionUtils.isEmpty(request.getPluginCodes())) {
      missionMapper.addMissionPluginRelation(request.getPluginCodes(), request.getCode());
      addMissionPluginRelationRedis(request.getPluginCodes(), request.getCode());
    }
    //添加关联的Proxy信息
    if (!CollectionUtils.isEmpty(request.getProxyCodes())) {
      missionMapper.addMissionProxyRelation(request.getProxyCodes(), request.getCode());
      addMissionProxyRelationRedis(request.getProxyCodes(), request.getCode());
    }
  }

  private void filterDataSoucureAvailable(MissionRequestDTO request) {
    if(StringUtils.isEmpty(request.getDataSourceConfig())){
      return;
    }
    SourceConfig sourceConfig = JSONObject.parseObject(request.getDataSourceConfig(), SourceConfig.class);
    if(CollectionUtils.isEmpty(sourceConfig.getSourceCodeList())){
      return;
    }

    MissionInfo missionByCode = missionMapper.getMissionByCode(request.getCode());
    if(ObjectUtils.isEmpty(missionByCode)){
      return;
    }
    List<String> sourceCodes = sourceConfig.getSourceCodeList();
    List<String> availableSourceCode = sourceCodes.stream().filter(sourceCode -> {
      DatasourceInfo dataSource = datasourceService.getDataSourceByCode(sourceCode);
      DataPreAvailableInfo dataPreAvailableInfo = dataPreAvailableService.getUseDataCountByFilterAndSourceCode(missionByCode, sourceCode);
      int useCount = 0;
      if (!ObjectUtils.isEmpty(dataPreAvailableInfo) && !ObjectUtils.isEmpty(dataPreAvailableInfo.getMissionUseCount())){
        useCount = dataPreAvailableInfo.getMissionUseCount().intValue();
      }
      return dataSource.getDataCount() - useCount > 0 ? true : false;

    }).collect(Collectors.toList());

    if(CollectionUtils.isEmpty(availableSourceCode)){
      throw new ServiceException(ErrorCodeConstants.AVAILABLE_DATA_SOURCE_IS_ZERO.getMsg());
    }
    QuestionShowInfo missionQuession = questionInfoService.getQuestionInfosByMissionTypeAndCode(QuestionInfoTypeEnum.MISSION.name(), missionByCode.getCode());
    if(!ObjectUtils.isEmpty(missionQuession)){
      String key = RedisKeyConstants.QUESTION_FIX_INFO.formatKey(missionByCode.getCode(), missionQuession.getCode());
      if(!redisService.hasKey(key)){
        redisService.setCacheObject(key,true);
      }
    }
    sourceConfig.setSourceCodeList(availableSourceCode);
    request.setDataSourceConfig(JSONObject.toJSONString(sourceConfig));

  }

  private void deleteCache(String code) {
    missionMapper.deleteMissionDeviceGroupRelation(code);
    missionMapper.deleteMissionDeviceFraudRelation(code);
    missionMapper.deleteMissionFlowFilterRelation(code);
    missionMapper.deleteMissionIpFraudRelation(code);
    missionMapper.deleteMissionPluginRelation(code);
    missionMapper.deleteMissionProxyRelation(code);
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_PROXY.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_PLUGIN.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_IP_FRAUD.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_FLOW_FILTER.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_DEVICE_FRAUD.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.RELATION_MISSION_DEVICE_GROUP.formatKey(code));
    redisService.deleteObject(RedisKeyConstants.MISSION_INFO.formatKey(code));
  }

  @Override
  public Boolean getMissionStatus(String code, MissionInfo missionInfo) {
    Object o = redisService.redisTemplate.opsForValue()
        .get(RedisConstants.MISSION_MAX_FAILED + code);
    if (ObjectUtils.isEmpty(o)) {
      return missionInfo.getStatus();
    }
    long times = Long.parseLong(o.toString());
    return times <= missionInfo.getPageStatusThreshold();
  }

  @Override
  public void initMissionNormalState(String code, boolean status) {
    //重置缓存为0
    redisService.setCacheObject(RedisConstants.MISSION_PAGE_FAILED_COUNT + code, 0);
    //删除缓存中异常状态
    redisService.deleteObject(RedisConstants.MISSION_NOT_NORMAL_STATE + code);
    //添加需要重置任务异常状态的缓存
    redisService.redisTemplate.opsForValue().setIfAbsent(RedisConstants.MISSION_NEED_INIT + code, 1);

    //Integer failedCount = null;
    //if (status) {
    //  failedCount = 0;
    //}
    //missionMapper.initMissionNormalState(code, status, failedCount);
  }

  @Override
  public void setMissionFailedCount(String code, boolean status) {
    if (status) {
      redisService.redisTemplate.opsForValue().set(RedisConstants.MISSION_MAX_FAILED + code, 0);
    } else {
      redisService.redisTemplate.opsForValue().increment(RedisConstants.MISSION_MAX_FAILED + code);
    }
  }

  @Override
  public boolean getDataCanSend(String dataCode, MissionInfo missionInfo,
      SourceConfig sourceConfig, List<String> indexTableNameList, Map<String, Object> sendDataMap) {
    Integer useCountByMission;
    String duplicateValue = "";
//    if (DuplicateConditionEnum.BY_NAME.name().equals(sourceConfig.getDuplicateCondition())) {
//      duplicateValue = dataCode + "_" + missionInfo.getMissionName();
//      //先看redis里面是否有唯一键
//      if (!redisService.redisTemplate.opsForValue()
//          .setIfAbsent(ClientServiceImpl.DATA_GET_LOCK + duplicateValue, 1, 5, TimeUnit.MINUTES)) {
//        return false;
//      }
//      //按名称
//      useCountByMission = dataSendByMissionService.useCountByMission(dataCode,
//          missionInfo.getMissionName(), null, null, null, indexTableNameList);
//    } else
      if (DuplicateConditionEnum.BY_MISSION_ID.name()
        .equals(sourceConfig.getDuplicateCondition())) {
      //按任务id
      //先看自己id本身有没有
      duplicateValue = dataCode + "_" + missionInfo.getCode();
      if (!redisService.redisTemplate.opsForValue()
          .setIfAbsent(ClientServiceImpl.DATA_GET_LOCK + duplicateValue, 1, 5, TimeUnit.MINUTES)) {
        return false;
      }
      sourceConfig.getCodeList().add(missionInfo.getCode());
      useCountByMission = dataSendByMissionService.useCountByMission(dataCode, null,
          sourceConfig.getCodeList(), null, null, indexTableNameList);
    } else if (DuplicateConditionEnum.BY_AFFILIATE_ID.name()
        .equals(sourceConfig.getDuplicateCondition())) {
      //按联盟id
      //先看自己id本身有没有
      duplicateValue = dataCode + "_" + missionInfo.getAffiliateCode();
      if (!redisService.redisTemplate.opsForValue().setIfAbsent(
          ClientServiceImpl.DATA_GET_LOCK + duplicateValue, 1, 5, TimeUnit.MINUTES)) {
        return false;
      }
      sourceConfig.getCodeList().add(missionInfo.getAdvertiserCode());
      useCountByMission = dataSendByMissionService.useCountByMission(dataCode, null,
          null, sourceConfig.getCodeList(), null, indexTableNameList);
    } else if (DuplicateConditionEnum.BY_ADVERTISER_ID.name().equals(sourceConfig.getDuplicateCondition())) {
      //按广告主id
      //先看自己id本身有没有
      duplicateValue = dataCode + "_" + missionInfo.getAdvertiserCode();
      if (!redisService.redisTemplate.opsForValue().setIfAbsent(
          ClientServiceImpl.DATA_GET_LOCK + duplicateValue, 1, 5, TimeUnit.MINUTES)) {
        return false;
      }
      sourceConfig.getCodeList().add(missionInfo.getAdvertiserCode());
      useCountByMission = dataSendByMissionService.useCountByMission(dataCode, null,
          null, null, sourceConfig.getCodeList(), indexTableNameList);
    } else {
      //没有配置去重条件,直接当做不通过
      return false;
    }
    if (!ObjectUtils.isEmpty(useCountByMission) && useCountByMission > 0) {
      return false;
    }
    Integer failedCount = dataSendByMissionService.getFailedCount(missionInfo.getCode(), dataCode);
    boolean resultFlag =
        ObjectUtils.isEmpty(failedCount) || failedCount < missionInfo.getLimitationCount();
    if (resultFlag) {
      sendDataMap.put(ClientServiceImpl.DATA_GET_LOCK_VALUE, duplicateValue);
    }
    return resultFlag;
  }

  @Override
  public void deleteMission(String missionCode, Long userId) {
    Integer delete = missionMapper.deleteMission(missionCode, userId);
    if (delete == 0) {
      throw new ServiceException("code不存在");
    }
    deleteCache(missionCode);
  }

  @Override
  public void incrementFailedCount(String code) {
    missionMapper.incrementFailedCount(code);
  }

  @Override
  @DataScope(deptAlias = "dept", userAlias = "su")
  public List<String> getMissionForHistory() {
    return missionMapper.getMissionForHistory();
  }

  @Override
  public List<MissionInfo> getMissionListByGroupCodes(String deviceGroupCode, String deptCode,
      boolean normalState) {
    if (normalState) {
      return missionMapper.getNormalMissionListByGroupCodes(deviceGroupCode);
    } else {
      return missionMapper.getNotNormalMissionListByGroupCodes(deptCode);
    }
  }

  @Override
  public void changeMissionStatus(String missionCode, boolean status) {
    missionMapper.changeMissionStatus(missionCode, status, SecurityUtils.getLoginUser().getUserId());
  }

  @Override
  public Long getFailedCountByMissionCode(String missionCode) {
    return missionMapper.getFailedCountByMissionCode(missionCode);
  }

  @Override
  public void updateMissionAndSourceAllCountBySourceCode(Integer intValue, String dataSourceCode, String sourceType) {
    missionMapper.updateMissionAndSourceAllCountBySourceCode(intValue, dataSourceCode);
  }

  @Override
  public void incrementMissionAndSourceUseCountBySourceCode(String missionCode, String sourceCode) {
    missionMapper.incrementMissionAndSourceUseCountBySourceCode(missionCode, sourceCode);
  }

  @Override
  public void decrementMissionAndSourceUseCountBySourceCode(String missionCode, String sourceCode) {
    missionMapper.decrementMissionAndSourceUseCountBySourceCode(missionCode, sourceCode);
  }

  @Override
  public void updtateMissionStatusByMissionCode(Integer status, String code) {
    missionMapper.updtateMissionStatusByMissionCode(status,code);
  }

  @Override
  public MissionInfo getMissionDetailByCode(String missionCode, boolean detail) {
    MissionInfo missionByCode = missionMapper.getMissionByCode(missionCode);
    if(!ObjectUtils.isEmpty(missionByCode)){
      //获取数据源
      DatasourceOptionRequestDTO datasourceOptionRequestDTO = new DatasourceOptionRequestDTO();
      List<DatasourceInfo> datasourceInfos = datasourceService.getAllDataSource(datasourceOptionRequestDTO);
      List<String> sourceCodes = datasourceInfos.stream().map(DatasourceInfo::getCode).collect(Collectors.toList());
      if (!CollectionUtils.isEmpty(sourceCodes)){

        SourceConfig sourceConfig = JSONObject.parseObject(missionByCode.getDataSourceConfig(), SourceConfig.class);
        if (!ObjectUtils.isEmpty(sourceConfig) && !CollectionUtils.isEmpty(sourceConfig.getSourceCodeList())){
          List<String> sourceCodeList = sourceConfig.getSourceCodeList();
          Iterator<String> iterator = sourceCodeList.iterator();
          while (iterator.hasNext()){
            if(!sourceCodes.contains(iterator.next())){
              iterator.remove();
            }
          }
        }
        missionByCode.setDataSourceConfig(JSONObject.toJSONString(sourceConfig));
      }

    }
    getMissionDetail(missionCode,true,missionByCode);
    return missionByCode;
  }

  @Override
  public void updateMissionUseDataCountRelation(String datasourceCode) {
    missionMapper.updateMissionUseDataCountRelation(datasourceCode);
  }

  @Override
  public void initMission(String missionCode){
    missionMapper.initMission(missionCode,SecurityUtils.getUserId());
  }

}
